#include "gpuinfo.h"
#include <d3d9.h>
#include <QLibrary>
#include <QTextStream>

void GpuInfo::detect()
{
    typedef IDirect3D9 * (WINAPI *PtrDirect3DCreate9)(UINT);

    QLibrary d3d9lib(QStringLiteral("d3d9"));
    if (!d3d9lib.load()) {
        return;
    }

    PtrDirect3DCreate9 direct3DCreate9 = (PtrDirect3DCreate9)d3d9lib.resolve("Direct3DCreate9");
    if (!direct3DCreate9) {
        return;
    }

    IDirect3D9 *direct3D9 = direct3DCreate9(D3D_SDK_VERSION);
    if (!direct3D9) {
        return;
    }

    D3DADAPTER_IDENTIFIER9 adapterIdentifier;
    const HRESULT hr = direct3D9->GetAdapterIdentifier(0, 0, &adapterIdentifier);
    direct3D9->Release();
    if (SUCCEEDED(hr)) {
        vendorId = adapterIdentifier.VendorId;
        deviceId = adapterIdentifier.DeviceId;
        revision = adapterIdentifier.Revision;
        subSysId = adapterIdentifier.SubSysId;
        QVector<int> version(4, 0);
        version[0] = HIWORD(adapterIdentifier.DriverVersion.HighPart); // Product
        version[1] = LOWORD(adapterIdentifier.DriverVersion.HighPart); // Version
        version[2] = HIWORD(adapterIdentifier.DriverVersion.LowPart); // Sub version
        version[3] = LOWORD(adapterIdentifier.DriverVersion.LowPart); // build
        driverVersion = QVersionNumber(version);
        driverName = adapterIdentifier.Driver;
        description = adapterIdentifier.Description;
    }
}

QString GpuInfo::toString() const
{
    QString result;
    QTextStream str(&result);
    str << "\n         Card Name: " << description
        << "\n       Driver Name: " << driverName
        << "\n    Driver Version: " << driverVersion.toString()
        << "\n         Vendor ID: 0x" << qSetPadChar(QLatin1Char('0'))
        << uppercasedigits << hex << qSetFieldWidth(4) << vendorId
        << "\n         Device ID: 0x" << qSetFieldWidth(4) << deviceId
        << "\n         SubSys ID: 0x" << qSetFieldWidth(8) << subSysId
        << "\n       Revision ID: 0x" << qSetFieldWidth(4) << revision
        << dec;
    return result;
}

QVariant GpuInfo::toVariant() const
{
    QVariantMap result;
    result.insert(QStringLiteral("vendorId"), QVariant(vendorId));
    result.insert(QStringLiteral("deviceId"), QVariant(deviceId));
    result.insert(QStringLiteral("subSysId"),QVariant(subSysId));
    result.insert(QStringLiteral("revision"), QVariant(revision));
    result.insert(QStringLiteral("driver"), QVariant(QLatin1String(driverName)));
    result.insert(QStringLiteral("driverProduct"), QVariant(driverVersion.segmentAt(0)));
    result.insert(QStringLiteral("driverVersion"), QVariant(driverVersion.segmentAt(1)));
    result.insert(QStringLiteral("driverSubVersion"), QVariant(driverVersion.segmentAt(2)));
    result.insert(QStringLiteral("driverBuild"), QVariant(driverVersion.segmentAt(3)));
    result.insert(QStringLiteral("driverVersionString"), driverVersion.toString());
    result.insert(QStringLiteral("description"), QVariant(QLatin1String(description)));
    result.insert(QStringLiteral("printable"), QVariant(toString()));
    return result;
}

QString GpuInfo::vendorIdString() const
{
    QString result;
    QTextStream str(&result);
    str << "0x" << qSetPadChar(QLatin1Char('0'))
        << uppercasedigits << hex << qSetFieldWidth(4) << vendorId;
    return result;
}

QString GpuInfo::deviceIdString() const
{
    QString result;
    QTextStream str(&result);
    str << "0x" << qSetPadChar(QLatin1Char('0')) << uppercasedigits << hex << qSetFieldWidth(4) << deviceId;
    return result;
}

QString GpuInfo::driverVersionString() const {
    return driverVersion.toString();
}
